#include "launch/include_parser.h"
#include "logger.h"
#include "utils/utils.h"
#include "utils/string_util.h"
#include "utils/common_utils.h"
#include "launch/launch_parser.h"
#include <filesystem>

const std::string FIND_PACKAGE_PREFIX = "$(find ";

IncludeParser::IncludeParser()
{}
std::optional<LaunchNode> IncludeParser::parser(const tinyxml2::XMLElement *element)
{
    //只支持file attribute
    const char *attribute;
    tinyxml2::XMLError xmlError = element->QueryAttribute("file", &attribute);
    if (tinyxml2::XMLError::XML_SUCCESS != xmlError)
    {
        ROS_ERROR("include parser get file attribute fail, xml: %s", Utils::formatElement(element).c_str());
        return std::nullopt;
    }
    return parserInclude(attribute);
}
std::optional<LaunchNode> IncludeParser::parserInclude(const std::string &fileAttribute)
{
    std::string launchPath;
    if (!utils::StringUtil::startsWith(fileAttribute, FIND_PACKAGE_PREFIX))
    {
        //不需要找包路径
        launchPath = fileAttribute;
    }
    else
    {
        if (auto path = getPackageLaunchFile(fileAttribute))
        {
            launchPath = path.value();
        }
        else
        {
            return std::nullopt;
        }
    }

    LaunchParser launchParser;
    return launchParser.parserLaunchFile(launchPath);
}
std::optional<std::string> IncludeParser::getPackageLaunchFile(const std::string &fileAttribute)
{
    std::vector<std::string> split = utils::StringUtil::split(fileAttribute, ")/", utils::SkipEmptyParts);
    if (split.size() != 2)
    {
        ROS_ERROR("include file attribute get package/launch name fail, file attribute: %s", fileAttribute.c_str());
        return std::nullopt;
    }
    std::string packageName = split.at(0);
    packageName = packageName.substr(packageName.find(FIND_PACKAGE_PREFIX) + FIND_PACKAGE_PREFIX.length());
    std::string launchName = split.at(1);

    std::vector<std::string> packagePathList = CommonUtils::getPackagePath(packageName);
    if (packagePathList.empty())
    {
        ROS_ERROR("cannot find package [%s] path", packageName.c_str());
        return std::nullopt;
    }
    if (packagePathList.size() > 1)
    {
        ROS_ERROR("there are the same package exist");
        return std::nullopt;
    }
    std::filesystem::path path(packagePathList.at(0));
    std::filesystem::path launchNamePath(launchName);

    path = path / launchNamePath;
    return path.string();
}
